const constants = require('../common/Constants.js');
const cryptManager = require('./cryptManager');
const requestInfoUtils = require('./RequestInfoUtils');
const responseInfoUtils = require('./ResponseInfoUtils');
const turnAroundUtils = require('./TurnAroundUtils');
import PageRouter from '../utils/PageRouter';
import LoginUtils from '../model/LoginUtils';
import * as UmfDialog from '../utils/UmfDialog';
import UmfLog from '../utils/UmfLog';


function requestConfig() {
    //url
    this.url = '';
    //请求头
    this.header = {
        'Content-Type': 'application/json',
    };
    //请求参数
    this.params = {};
    //是否显示等待对话框
    this.loading = true;
    this.netMethod = 'POST';
    //通信加解密数据
    this.safeSdk = {};
    this.callback = {
        httpCallPreFilter: () => {
            //网络请求前处理
            this.loading && wx.showToast({
                title: '加载中',
                icon: 'loading',
                mask: true,
                duration: 30000,
            });
        },
        httpCallBackPreFilter: (response) => {
            if (constants.RetCodes.SESSION_OUT === response["retCode"]) {
                UmfLog.log("登录超时");
                //清空用户数据、session
                LoginUtils.clearLoginData();
                PageRouter.anyNavigateTo("pages/login/login", "?from=" + constants.LoginFrom.SESSION_OUT, (curPage)=> {
                    curPage.setData({
                        errorMsg: "登录超时，请重新登录"
                    });
                });
                return true;
            } else if (constants.RetCodes.KICK_OUT === response["retCode"]) {
                UmfLog.log("被踢掉");
                //清空用户数据、session
                LoginUtils.clearLoginData();
                PageRouter.anyNavigateTo("pages/login/login", "?from=" + constants.LoginFrom.KICK_OUT, (curPage)=> {
                    curPage.setData({
                        errorMsg: "您的账号在其他设备登录，请重新登录"
                    });
                });
                return true;
            } else if (constants.RetCodes.USER_STATE_CLOSED === response["retCode"]) {
                UmfLog.log("被停用");
                //清空用户数据、session
                LoginUtils.clearLoginData();
                PageRouter.anyNavigateTo("pages/login/login", "?from=" + constants.LoginFrom.USER_STATE_CLOSED, (curPage)=> {
                    UmfDialog.show("您的账号已被管理员admin停用,如需启用请联系管理员.");
                });
                return true;
            } else if (constants.RetCodes.USER_STATE_NO_PERM === response["retCode"]) {
                UmfLog.log("权限变更");
                //清空用户数据、session
                LoginUtils.clearLoginData();
                PageRouter.anyNavigateTo("pages/login/login", "?from=" + constants.LoginFrom.USER_STATE_NO_PERM, (curPage)=> {
                    UmfDialog.show("您的权限已被管理员admin修改,请重新登录.");
                });
                return true;
            }
            return false;
        },
        doHttpSucess: (response) => {
            //网络请求成功--公共处理
            if (constants.RetCodes.SUCCESS !== response["retCode"]) {
                wx.showModal({
                    title: '提示',
                    content: response.retMsg,
                    showCancel: false
                });
            }
        },
        doHttpFailure: (response) => {
            //网络请求失败--公共处理
            wx.showModal({
                title: '提示',
                content: response.retMsg,
                showCancel: false
            });
        },
        doComplete: () => {
            //网络请求结束--公共处理
            this.loading && setTimeout(() => {
                wx.hideToast();
            }, 500);
        }
    };

    this.setMethodGet = function () {
        this.netMethod = 'GET';
        return this;
    };

    this.send = function () {
        _request(this);
    };

    this.upload = function (filePath) {
        _upload(this, filePath);
    }
}

function httpResponse() {
    //服务器返回结果数据
    this.result = '';
    //rpid
    this.rpid = '';
    //服务器返回消息
    this.retMsg = '';
    //结果码
    this.retCode = '';
    //请求配置信息
    this.requestConfig = {};

    this.isSucess = () => {
        return constants.RetCodes.SUCCESS === this.retCode;
    };

    this.create = (retCode, retMsg, rpid, result) => {
        this.result = result;
        this.rpid = rpid;
        this.retMsg = retMsg;
        this.retCode = retCode;
        return this;
    };
}

/**
 * 注意,此方法调用后还要调用.send()才是发送出去.
 * @param Interfaces
 * @param protocol
 * @param params
 * @param callback  拷贝上方注释区的代码使用
 * @param loading
 * @returns {requestConfig}
 */
function buildRequest(url, params, callback, loading=true) {
    UmfLog.log("=====================UmpHttp request=====================");
    if (constants.dangban && turnAroundUtils.UrlList.contains(url)) {
        UmfLog.log("=====================DangBan=====================");
        return turnAroundUtils.buildRequest(url, params, callback, loading);
    }

    let config = new requestConfig();
    config.loading = loading;

    config.url = constants.url() + url;
    config.params = params;
    if (_isFunction(callback.httpCallPreFilter)) {
        let pubHttpCallPreFilter = config.callback.httpCallPreFilter;
        config.callback.httpCallPreFilter = () => {
            if (!callback.httpCallPreFilter()) {
                pubHttpCallPreFilter();
            }
        }
    }
    if (_isFunction(callback.httpCallBackPreFilter)) {
        let pubHttpCallBackPreFilter = config.callback.httpCallBackPreFilter;
        config.callback.httpCallBackPreFilter = (response) => {
            if (!callback.httpCallBackPreFilter(response)) {
                pubHttpCallBackPreFilter(response);
            }
        }
    }
    if (_isFunction(callback.doHttpSucess)) {
        let pubDoHttpSucess = config.callback.doHttpSucess;
        config.callback.doHttpSucess = (response) => {
            if (!callback.doHttpSucess(response)) {
                pubDoHttpSucess(response);
            }
        }
    }
    if (_isFunction(callback.doHttpFailure)) {
        let pubDoHttpFailure = config.callback.doHttpFailure;
        config.callback.doHttpFailure = (response) => {
            if (!callback.doHttpFailure(response)) {
                pubDoHttpFailure(response);
            }
        }
    }

    if (_isFunction(callback.doComplete)) {
        let pubDoComplete = config.callback.doComplete;
        config.callback.doComplete = () => {
            if (!callback.doComplete()) {
                pubDoComplete();
            }
        }
    }
    return config;
}

/**
 * 请求数据
 * @param requestConfig
 * @private
 */
function _request(requestConfig) {
    //请求发出前
    requestConfig.callback.httpCallPreFilter();
    UmfLog.log("[HTTP] url: " + requestConfig['url']);
    let secretData = processRequest(requestConfig);
    let formData = {
        secretData: secretData["secretData"]
    };
    wx.request({
        url: requestConfig['url'],
        method: requestConfig['netMethod'],
        data: formData,
        header: requestConfig['header'],
        success: (res) => {
            _requestSuccess(res, requestConfig);
        },
        fail: (res) => {
            _requestFailed(res, requestConfig)
        },
        complete: (res) => {
            requestConfig.callback.doComplete();
        }
    })
}

/**
 * 上传文件
 * @param requestConfig 请求配置
 * @param filePath 本地文件路径
 * @private
 */
function _upload(requestConfig, filePath) {
    //请求发出前
    requestConfig.callback.httpCallPreFilter();
    UmfLog.log("[HTTP] url: " + requestConfig['url']);
    let secretData = processRequest(requestConfig);
    let formData = {
        secretData: secretData["secretData"]
    };
    let headers = {
        'Content-Type': 'multipart/form-data',
        'formData': JSON.stringify(formData)
    };
    headers = Object.assign(requestConfig['header'], headers)

    wx.uploadFile({
        header: headers,
        method: requestConfig['netMethod'],
        url: requestConfig['url'],
        filePath: filePath,
        name: 'file',
        success: (res) => {
            _requestSuccess(res, requestConfig);
        },
        fail: (res) => {
            _requestFailed(res, requestConfig);
        },
        complete: () => {
            requestConfig.callback.doComplete();
        }
    })
}

function processRequest(requestConfig) {
    //处理参数
    requestInfoUtils.processParam(requestConfig.params);
    //转化为请求的形式
    let reqData = requestInfoUtils.convertReqData(requestConfig.params);
    //加密请求体
    let secretData = requestInfoUtils.encodeData(reqData);
    //获取请求头信息
    let httpHeader = requestInfoUtils.createHttpHeader(requestConfig.params, secretData.aesKey);

    //配置
    Object.assign(requestConfig.header, httpHeader);
    requestConfig.safeSdk = {aesKey: secretData.aesKey};
    return secretData;
}

function _callBack(response, callback) {
    if (callback) {
        if (response["retCode"] === "-1") {
            callback.doHttpFailure(response);
        } else {
            if (!callback.httpCallBackPreFilter(response)) {
                callback.doHttpSucess(response);
            }
        }
    }
}

function _requestSuccess(res, requestConfig) {
    UmfLog.log(res);
    if (parseInt(res.statusCode) === 200) {
        let response = res['data'];
        if (typeof response === 'string') {
            response = JSON.parse(response);
        }

        let safeResult = responseInfoUtils.decodeProcessResult(response, requestConfig.safeSdk);
        if (!safeResult) {
            UmfLog.error("安全层处理失败:" + safeResult);
            let response = new httpResponse().create(constants.RetCodes.NETWORK_ERROR, '请求失败，请重试');
            response.requestConfig = requestConfig;
            requestConfig.callback.doHttpFailure(response);
            return;
        }
        if (!safeResult.body) {
            UmfLog.error("安全层处理失败:" + safeResult);
            let response = new httpResponse().create(safeResult.retCode, safeResult.retMsg);
            response.requestConfig = requestConfig;
            requestConfig.callback.doHttpFailure(response);
            return;
        }

        try {
            let body = safeResult.body;
            let resultData = JSON.parse(body);
            UmfLog.log("[HTTP] response:");
            UmfLog.log(resultData);
            resultData.requestConfig = requestConfig;
            _callBack(resultData, requestConfig.callback);
        } catch (e) {
            UmfLog.error(e);
        }
    } else {
        let response = new httpResponse().create(constants.RetCodes.RESPONSE_ERROR, '请求失败');
        response.requestConfig = requestConfig;
        requestConfig.callback.doHttpFailure(response);
    }
}

function _requestFailed(res, requestConfig) {
    UmfLog.error("[HTTP]: requestFailed");
    UmfLog.error(res);
    let response = new httpResponse().create(constants.RetCodes.NETWORK_ERROR, '网络错误');
    response.requestConfig = requestConfig;
    requestConfig.callback.doHttpFailure(response);
}

function _isFunction(func) {
    if (typeof func === "function") {
        return true;
    }
    return false;
}

module.exports = {
    buildRequest: buildRequest
};